package com.iip.fabric.service.impl;


import com.iip.fabric.service.ChainService;
import lombok.extern.slf4j.Slf4j;
import org.hyperledger.fabric.gateway.*;
import org.hyperledger.fabric.gateway.impl.GatewayImpl;
import org.hyperledger.fabric.sdk.BlockInfo;
import org.hyperledger.fabric.sdk.BlockchainInfo;
import org.hyperledger.fabric.sdk.Channel;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.Properties;


@Slf4j
@Service
public class ChainServiceImpl implements ChainService {

    public Gateway gateway;
    public Network network;


    public byte[] query(String key) throws IOException, ContractException {

        try {
            //获取相应参数
            Properties properties = new Properties();
            InputStream inputStream = ChainServiceImpl.class.getResourceAsStream("/fabric.config.properties");
            properties.load(inputStream);

            String networkConfigPath =  "src/main/resources/connection.json";
            String channelName = properties.getProperty("channelName");
            String contractName = properties.getProperty("contractName");

            String certificatePath = properties.getProperty("certificatePath");
            X509Certificate certificate = validation.readX509Certificate(Paths.get(certificatePath));

            String privateKeyPath = properties.getProperty("privateKeyPath");
            PrivateKey privateKey = validation.getPrivateKey(Paths.get(privateKeyPath));

            Wallet wallet = Wallets.newInMemoryWallet();

            wallet.put("user",Identities.newX509Identity("Org1MSP",certificate,privateKey));

            //根据connection-org1.json 获取Fabric网络连接对象
            GatewayImpl.Builder builder = (GatewayImpl.Builder) Gateway.createBuilder().identity(wallet, "user").networkConfig(Paths.get(networkConfigPath));

            //连接网关
            gateway = builder.connect();
            //获取mychannel通道
            Network network = gateway.getNetwork(channelName);
            //获取合约对象
            Contract contract = network.getContract(contractName);
            //查询合约对象evaluateTransaction
            // Evaluate transactions that query state from the ledger.
            byte[] queryAResult = contract.evaluateTransaction("QueryFile",key);
            System.out.println("查询到的文件信息："+new String(queryAResult, StandardCharsets.UTF_8));

            return queryAResult;

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;

    }

    public boolean create(String key, String name, String size, String uptime, String owner, String operation) {

        try {
            //获取相应参数
            Properties properties = new Properties();
            InputStream inputStream = ChainServiceImpl.class.getResourceAsStream("/fabric.config.properties");
            properties.load(inputStream);

            String networkConfigPath = "src/main/resources/connection.json";
            String channelName = properties.getProperty("channelName");
            String contractName = properties.getProperty("contractName");

            String certificatePath = properties.getProperty("certificatePath");
            X509Certificate certificate = validation.readX509Certificate(Paths.get(certificatePath));

            String privateKeyPath = properties.getProperty("privateKeyPath");
            PrivateKey privateKey = validation.getPrivateKey(Paths.get(privateKeyPath));

            Wallet wallet = Wallets.newInMemoryWallet();

            wallet.put("user",Identities.newX509Identity("Org1MSP",certificate,privateKey));

            //根据connection-org1.json 获取Fabric网络连接对象
            GatewayImpl.Builder builder = (GatewayImpl.Builder) Gateway.createBuilder().identity(wallet, "user").networkConfig(Paths.get(networkConfigPath));

            //连接网关
            gateway = builder.connect();
            //获取mychannel通道
            Network network = gateway.getNetwork(channelName);
            //获取合约对象
            Contract contract = network.getContract(contractName);

            // Evaluate transactions that query state from the ledger.
            byte[] queryAResult = contract.submitTransaction("CreateFile",key, name, size, uptime, owner, operation);
//            System.out.println("提交结果："+new String(queryAResult, StandardCharsets.UTF_8));

            return true;

        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    public byte[] delete(String key) {

        try {
            //获取相应参数
            Properties properties = new Properties();
            InputStream inputStream = ChainServiceImpl.class.getResourceAsStream("/fabric.config.properties");
            properties.load(inputStream);

            String networkConfigPath =  "src/main/resources/connection.json";
            String channelName = properties.getProperty("channelName");
            String contractName = properties.getProperty("contractName");

            String certificatePath = properties.getProperty("certificatePath");
            X509Certificate certificate = validation.readX509Certificate(Paths.get(certificatePath));

            String privateKeyPath = properties.getProperty("privateKeyPath");
            PrivateKey privateKey = validation.getPrivateKey(Paths.get(privateKeyPath));

            Wallet wallet = Wallets.newInMemoryWallet();

            wallet.put("user",Identities.newX509Identity("Org1MSP",certificate,privateKey));

            //根据connection-org1.json 获取Fabric网络连接对象
            GatewayImpl.Builder builder = (GatewayImpl.Builder) Gateway.createBuilder().identity(wallet, "user").networkConfig(Paths.get(networkConfigPath));

            //连接网关
            gateway = builder.connect();
            //获取mychannel通道
            Network network = gateway.getNetwork(channelName);
            //获取合约对象
            Contract contract = network.getContract(contractName);
            //查询合约对象evaluateTransaction
            // Evaluate transactions that query state from the ledger.
            byte[] queryAResult = contract.evaluateTransaction("QueryAllFiles");
            System.out.println("查询到的文件信息："+new String(queryAResult, StandardCharsets.UTF_8));

            return null;

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public byte[] queryfilehistory(String key) {

        try {
            //获取相应参数
            Properties properties = new Properties();
            InputStream inputStream = ChainServiceImpl.class.getResourceAsStream("/fabric.config.properties");
            properties.load(inputStream);

            String networkConfigPath = "src/main/resources/connection.json";
            String channelName = properties.getProperty("channelName");
            String contractName = properties.getProperty("contractName");

            String certificatePath = properties.getProperty("certificatePath");
            X509Certificate certificate = validation.readX509Certificate(Paths.get(certificatePath));

            String privateKeyPath = properties.getProperty("privateKeyPath");
            PrivateKey privateKey = validation.getPrivateKey(Paths.get(privateKeyPath));

            Wallet wallet = Wallets.newInMemoryWallet();

            wallet.put("user",Identities.newX509Identity("Org1MSP",certificate,privateKey));

            //根据connection-org1.json 获取Fabric网络连接对象
            GatewayImpl.Builder builder = (GatewayImpl.Builder) Gateway.createBuilder().identity(wallet, "user").networkConfig(Paths.get(networkConfigPath));

            //连接网关
            gateway = builder.connect();
            //获取mychannel通道
            Network network = gateway.getNetwork(channelName);
            //获取合约对象
            Contract contract = network.getContract(contractName);
            //查询合约对象evaluateTransaction
            // Evaluate transactions that query state from the ledger.
            byte[] queryAResult = contract.evaluateTransaction("QueryFileHistory", key);
            System.out.println("查询到的文件信息："+new String(queryAResult, StandardCharsets.UTF_8));
            return queryAResult;

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    public String[] channelInfo(){
        try {
            //获取相应参数
            Properties properties = new Properties();
            InputStream inputStream = ChainServiceImpl.class.getResourceAsStream("/fabric.config.properties");
            properties.load(inputStream);

            String networkConfigPath = "src/main/resources/connection.json";
            String channelName = properties.getProperty("channelName");
            String contractName = properties.getProperty("contractName");

            String certificatePath = properties.getProperty("certificatePath");
            X509Certificate certificate = validation.readX509Certificate(Paths.get(certificatePath));

            String privateKeyPath = properties.getProperty("privateKeyPath");
            PrivateKey privateKey = validation.getPrivateKey(Paths.get(privateKeyPath));

            Wallet wallet = Wallets.newInMemoryWallet();

            wallet.put("user",Identities.newX509Identity("Org1MSP",certificate,privateKey));

            //根据connection-org1.json 获取Fabric网络连接对象
            GatewayImpl.Builder builder = (GatewayImpl.Builder) Gateway.createBuilder().identity(wallet, "user").networkConfig(Paths.get(networkConfigPath));

            //连接网关
            gateway = builder.connect();
            //获取mychannel通道
            Network network = gateway.getNetwork(channelName);
            //获取合约对象
            Contract contract = network.getContract(contractName);
            //获取通道，然后获取区块信息
            Channel channel = network.getChannel();
            BlockchainInfo blockchainInfo = channel.queryBlockchainInfo();





            StringBuilder previousBlockHash = new StringBuilder();
            for(byte bite : blockchainInfo.getPreviousBlockHash()) {
                previousBlockHash.append(String.format("%02x", bite));
            }

            StringBuilder currentBlockHash = new StringBuilder();
            for(byte bite : blockchainInfo.getCurrentBlockHash()) {
                currentBlockHash.append(String.format("%02x", bite));
            }

            System.out.println("当前区块高度为:"+blockchainInfo.getHeight() + " ");
            System.out.println("前一区块哈希值:"+previousBlockHash + " ");
            System.out.println("当前区块哈希值:"+currentBlockHash + " ");

            String[] strArr = new String[3];
            strArr[0] = String.valueOf(blockchainInfo.getHeight());
            strArr[1] = previousBlockHash.toString();
            strArr[2] = currentBlockHash.toString();


            return strArr;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    public String blockInfo(long height){
        try {
            //获取相应参数
            Properties properties = new Properties();
            InputStream inputStream = ChainServiceImpl.class.getResourceAsStream("/fabric.config.properties");
            properties.load(inputStream);

            String networkConfigPath = "src/main/resources/connection.json";
            String channelName = properties.getProperty("channelName");
            String contractName = properties.getProperty("contractName");

            String certificatePath = properties.getProperty("certificatePath");
            X509Certificate certificate = validation.readX509Certificate(Paths.get(certificatePath));

            String privateKeyPath = properties.getProperty("privateKeyPath");
            PrivateKey privateKey = validation.getPrivateKey(Paths.get(privateKeyPath));

            Wallet wallet = Wallets.newInMemoryWallet();

            wallet.put("user",Identities.newX509Identity("Org1MSP",certificate,privateKey));

            //根据connection-org1.json 获取Fabric网络连接对象
            GatewayImpl.Builder builder = (GatewayImpl.Builder) Gateway.createBuilder().identity(wallet, "user").networkConfig(Paths.get(networkConfigPath));

            //连接网关
            gateway = builder.connect();
            //获取mychannel通道
            Network network = gateway.getNetwork(channelName);
            //获取合约对象
            Contract contract = network.getContract(contractName);
            //获取通道，然后获取区块信息
            Channel channel = network.getChannel();
//

            BlockInfo returnedBlock = channel.queryBlockByNumber(height);
            System.out.println("区块高度为："+returnedBlock.getBlockNumber());
            System.out.println("此区块中交易数量为："+returnedBlock.getTransactionCount());


            StringBuilder preBlockHash = new StringBuilder();
            for(byte bite : returnedBlock.getPreviousHash()) {
                preBlockHash.append(String.format("%02x", bite));
            }
            System.out.println("前一区块哈希值:"+ preBlockHash);


            StringBuilder curBlockHash = new StringBuilder();
            for(byte bite : returnedBlock.getDataHash()) {
                curBlockHash.append(String.format("%02x", bite));
            }
            System.out.println("当前区块哈希值:"+ curBlockHash);

            //只返回交易数量
            return String.valueOf(returnedBlock.getTransactionCount());

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;

    };
}
